//
//  CGGImage.m
//  PictureYourself
//
//  Created by Daniel on 8/8/12.
//
//

#import "CGGImage.h"

@implementation CGGImage

CGFloat DegreesToRadians(CGFloat degrees) {return degrees * M_PI / 180;};

void thumbnailDataProviderReleaseCallback(void *info, const void *data, size_t size)
{
}

CGImageRef thumbnailCreateFromData2(NSData* jpegData, int size)
{
    CGImageSourceRef image_source = CGImageSourceCreateWithData((CFDataRef)jpegData, NULL);
    CFDictionaryRef options_dictionary = CGImageSourceCopyPropertiesAtIndex(image_source, 0, NULL);
    CGImageRef image = CGImageSourceCreateImageAtIndex(image_source, 0, options_dictionary);
    
    if(options_dictionary)
        CFRelease(options_dictionary);
    
    CGImageRef thumbnail = thumbnailCreateFromImage(image, size);
    CGImageRelease(image);
    CFRelease(image_source);
    return thumbnail;
}

// This method does not directly translate an EXIF orientation to UIImageOrientation - what it does is specifies which UIImageOrientation rotation to apply to the image in order to view it in it's correct orientation
UIImageOrientation uiImageOrientationToApply(CFDictionaryRef image_properties)
{    
    CFNumberRef exif_orientation_ref = CFDictionaryGetValue(image_properties, kCGImagePropertyOrientation);
    CFIndex exif_orientation_number;
    
    if(!CFNumberGetValue(exif_orientation_ref, kCFNumberCFIndexType, &exif_orientation_number))
    {
        NSLog(@"!!! Failed to get CFNumber from number ref\n");
        return UIImageOrientationUp;
    }
    
    UIImageOrientation cocoa_orientation_to_apply;
    
    switch (exif_orientation_number)
    {
        case 1:
            cocoa_orientation_to_apply = UIImageOrientationUp;
            break;
        case 3:
            cocoa_orientation_to_apply = UIImageOrientationDown;
            break;
        case 6:
            cocoa_orientation_to_apply = UIImageOrientationRight;
            break;
        case 8:
            cocoa_orientation_to_apply = UIImageOrientationLeft;
            break;
        
        default:
            NSLog(@"Failed to translate EXIF orientation %ld to UIImageOrientation\n", exif_orientation_number);
            return UIImageOrientationUp;
    }
    
    //NSLog(@"Should apply UIImageOrientation %d to counter exif orientation %@\n", cocoa_orientation_to_apply, exif_orientation_ref);
    
    return cocoa_orientation_to_apply;
}

int orientationToApplyByDegrees(CFDictionaryRef image_properties)
{
    CFNumberRef exif_orientation_ref = CFDictionaryGetValue(image_properties, kCGImagePropertyOrientation);
    CFIndex exif_orientation_number;
    
    if(!CFNumberGetValue(exif_orientation_ref, kCFNumberCFIndexType, &exif_orientation_number))
    {
        NSLog(@"!!! Failed to get CFNumber from number ref\n");
        return UIImageOrientationUp;
    }
    
    int rotation_to_apply;
    
    switch (exif_orientation_number)
    {
        case 1:
            rotation_to_apply = 0;
            break;
        case 3:
            rotation_to_apply = 180;
            break;
        case 6:
            rotation_to_apply = 90;
            break;
        case 8:
            rotation_to_apply = -90;
            break;
            
        default:
            NSLog(@"Failed to translate EXIF orientation %ld to rotation\n", exif_orientation_number);
            return UIImageOrientationUp;
    }
    
    //NSLog(@"Should apply UIImageOrientation %d to counter exif orientation %@\n", rotation_to_apply, exif_orientation_ref);
    
    return rotation_to_apply;
}

CGImageRef thumbnailCreateFromImage(CGImageRef image, int size)
{
    CGFloat width = size;
    CGFloat height = size;
    size_t originalWidth = CGImageGetWidth(image);
    size_t originalHeight = CGImageGetHeight(image);
    
    CGRect cropRect;
    
    if(originalWidth > originalHeight)
        cropRect = CGRectMake((originalWidth - originalHeight) / 2, 0, originalHeight, originalHeight);
    else
        cropRect = CGRectMake(0, (originalHeight - originalWidth) / 2, originalWidth, originalWidth);
    
    CGImageRef croppedImage = CGImageCreateWithImageInRect(image, cropRect);
    
    CGColorSpaceRef colorSpace = CGImageGetColorSpace(croppedImage);
    CGImageAlphaInfo alpha = CGImageGetAlphaInfo(croppedImage);
    size_t componentsPerPixel = CGColorSpaceGetNumberOfComponents(colorSpace) + (alpha == kCGImageAlphaNone ? 0 : 1);
    size_t bitsPerComponent = CGImageGetBitsPerComponent(croppedImage);
    size_t bytesPerPixel = (bitsPerComponent * componentsPerPixel + 7)/8;

    CGContextRef bitmap = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerPixel * width, colorSpace, alpha);
    
    CGContextTranslateCTM(bitmap, width / 2, height / 2);
    CGContextClipToRect(bitmap, CGRectMake(-(width / 2), -(height / 2), width, height));
    
    // Draw into the context, this scales the image
	CGContextDrawImage(bitmap, CGRectMake(- (width / 2), -(height / 2), width, height), croppedImage);
    CGImageRelease(croppedImage);
    
	CGImageRef thumbnail = CGBitmapContextCreateImage(bitmap);
    
	CGContextRelease(bitmap);
	
    return thumbnail;
}

@end
